package com.vgemv.jsutilitysdk.GajPcmToWavService;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.os.Looper;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class GajPcmToWavManager {

        /**
         * 缓存的音频大小
         */
        private int mBufferSize;
        /**
         * 采样率
         */
        private int mSampleRate;
        /**
         * 声道数
         */
        private int mChannel;

        private int mi_depthInBit;
        private Thread mThread_pcmToWav;
        public IGajPcmToWavManagerCallback mCallback;


        /**
         * @param sampleRate sample rate、采样率
         * @param channelConfig channel、声道
         * AudioFormat.CHANNEL_IN_MONO
         * AudioFormat.CHANNEL_IN_STEREO
         * @param encoding Audio data format、音频格式,需要指定深度.
         * AudioFormat.ENCODING_PCM_16BIT
         */
        public GajPcmToWavManager(int sampleRate, int channelConfig, int encoding) {
            this.mSampleRate = sampleRate;
            this.mChannel = channelConfig;
            //如果encoding是AudioFormat.ENCODING_PCM_16BIT,则是16.
            mi_depthInBit = 16;
            //生成最小的buffer大小.
            this.mBufferSize = AudioRecord.getMinBufferSize(mSampleRate, mChannel, encoding);
        }


        /**
         * pcm文件转wav文件
         *
         * @param inFilename 源文件路径
         * @param outFilename 目标文件路径
         */
        public void pcmToWav(final String inFilename,final String outFilename) {

            mThread_pcmToWav = new Thread() {

                @Override
                public void run() {

                    Looper.prepare();
                    //输入到内存的数据流
                    FileInputStream in;
                    //输出到文件的数据流
                    FileOutputStream out;

                    long totalAudioLen;
                    long totalDataLen;
                    long longSampleRate = mSampleRate;
                    int channels = mChannel == AudioFormat.CHANNEL_IN_MONO ? 1 : 2;

                    //音频比特率
                    long audioByteRate = mi_depthInBit * mSampleRate * channels / 8;

                    byte[] data = new byte[mBufferSize];
                    try {
                        in = new FileInputStream(inFilename);
                        out = new FileOutputStream(outFilename);
                        totalAudioLen = in.getChannel().size();
                        //为什么totalDataLen要加上36? 明明多了44字节,为什么总长度说是多了33?
                        totalDataLen = totalAudioLen + 36;
                        writeWaveFileHeader(out, totalAudioLen, totalDataLen,
                                longSampleRate, channels, audioByteRate);
                        //其余内容,原样输出到文件中去.
                        //inputFile-->data-->outputFile;
                        while (in.read(data) != -1) {
                            out.write(data);
                        }
                        in.close();
                        out.close();
                        mCallback.onTransformCompleted();

                        Looper.loop();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            };
            mThread_pcmToWav.start();
        }


        /**
         * 加入wav文件头
         */
        private void writeWaveFileHeader(FileOutputStream out, long totalAudioLen,
                                         long totalDataLen, long longSampleRate, int channels, long byteRate)
                throws IOException {
            byte[] header = new byte[44];
            // RIFF/WAVE header
            header[0] = 'R';
            header[1] = 'I';
            header[2] = 'F';
            header[3] = 'F';
            header[4] = (byte) (totalDataLen & 0xff);
            header[5] = (byte) ((totalDataLen >> 8) & 0xff);
            header[6] = (byte) ((totalDataLen >> 16) & 0xff);
            header[7] = (byte) ((totalDataLen >> 24) & 0xff);
            //WAVE
            header[8] = 'W';
            header[9] = 'A';
            header[10] = 'V';
            header[11] = 'E';
            // 'fmt ' chunk
            header[12] = 'f';
            header[13] = 'm';
            header[14] = 't';
            header[15] = ' ';
            // 4 bytes: size of 'fmt ' chunk
            header[16] = 16;
            header[17] = 0;
            header[18] = 0;
            header[19] = 0;
            // format = 1
            header[20] = 1;
            header[21] = 0;
            header[22] = (byte) channels;
            header[23] = 0;
            header[24] = (byte) (longSampleRate & 0xff);
            header[25] = (byte) ((longSampleRate >> 8) & 0xff);
            header[26] = (byte) ((longSampleRate >> 16) & 0xff);
            header[27] = (byte) ((longSampleRate >> 24) & 0xff);
            header[28] = (byte) (byteRate & 0xff);
            header[29] = (byte) ((byteRate >> 8) & 0xff);
            header[30] = (byte) ((byteRate >> 16) & 0xff);
            header[31] = (byte) ((byteRate >> 24) & 0xff);
            // block align
            header[32] = (byte) (2 * 16 / 8);
            header[33] = 0;
            // bits per sample
            header[34] = 16;
            header[35] = 0;
            //data
            header[36] = 'd';
            header[37] = 'a';
            header[38] = 't';
            header[39] = 'a';
            header[40] = (byte) (totalAudioLen & 0xff);
            header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
            header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
            header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
            out.write(header, 0, 44);
        }
}
